package com.yc.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yc.JwtRequest;
import com.yc.Result;
import com.yc.entities.*;
import com.yc.security.utils.JwtTokenUtil;
import com.yc.service.BloodSugarDoctorService;
import com.yc.service.BloodSugarRoleService;
import com.yc.service.BloodSugarUserRoleService;
import com.yc.service.BloodSugarUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;


/**
 * JwtAuthenticationController
 * 	包含登陆和查看token的方法
 * @author kukaha
 */
@RestController
@CrossOrigin
@Slf4j
@Api(value = "JwtAuthenticationController", tags = { "用户认证相关接口" })
public class JwtAuthenticationController {


	@Autowired
	private PasswordEncoder passwordEncoder;

	/**
	 * 注入认证管理器
	 * @title
	 * @author kukaha
	 * @updateTime  16:13
	 */
	@Autowired
	private AuthenticationManager authenticationManager;

	/**
	 * 注入jwt token工具类
	 * @title
	 * @author kukaha
	 * @updateTime  16:13
	 */
	@Autowired
	private JwtTokenUtil jwtTokenUtil;

	@Autowired
	private RedisTemplate<String, Object> redisTemplate;

	/**
	 * 注入userDetails
	 * @title
	 * @author kukaha
	 * @updateTime  16:15
	 */
	@Autowired
	private UserDetailsService jwtUserDetailsServiceImpl;


	@Autowired
	private BloodSugarUserService bloodSugarUserService;
	@Autowired
	private BloodSugarUserRoleService bloodSugarUserRoleService;
	@Autowired
	private BloodSugarRoleService bloodSugarRoleService;
	@Autowired
	private BloodSugarDoctorService bloodSugarDoctorService;


	@Value("${jwt.header}")
	private String tokenHeader;

	/**
	 * 根据用户名密码获取token
	 * @title
	 * @author kukaha
	 * @updateTime  16:16
	 */
	@ApiOperation(value = "用户认证授权")
	@PostMapping("${jwt.route.authentication.path}")
	public Result createAuthenticationToken(@Valid @RequestBody JwtRequest authenticationRequest) throws Exception {
		log.info("username:"+authenticationRequest.getUsername(),"password:"+authenticationRequest.getPassword());
		String username = authenticationRequest.getUsername();
		String password = authenticationRequest.getPassword();
		QueryWrapper<BloodSugarUser> wrapper = new QueryWrapper<>();
		wrapper.eq("account",username);
		BloodSugarUser user = bloodSugarUserService.getOne(wrapper);
		if (user!=null){
			if ("1".equals(user.getIsDisable())){
				return Result.error().message("此账号已被禁用,请联系管理员");
			}
			LambdaQueryWrapper<BloodSugarUserRole> userRoleLambdaQueryWrapper = Wrappers.lambdaQuery();
			userRoleLambdaQueryWrapper.eq(BloodSugarUserRole::getUserId,user.getId());
			BloodSugarUserRole userRole = bloodSugarUserRoleService.getOne(userRoleLambdaQueryWrapper);
			BloodSugarRole role = bloodSugarRoleService.getById(userRole.getRoleId());
			if (!"0".equals(role.getRoleType())){
				QueryWrapper<BloodSugarDoctor> doctorWrapper = new QueryWrapper<>();
				doctorWrapper.eq("doctor_id",user.getId());
				BloodSugarDoctor doctor = bloodSugarDoctorService.getOne(doctorWrapper);
				if (doctor == null) {
					user.setDeanId(user.getId());
				}else {
					user.setUserName(doctor.getDoctorName());
					user.setDepartmentId(doctor.getDepartmentId());
					user.setDeanId(doctor.getDeanId());
				}
			}
			boolean isPassTrue = passwordEncoder.matches(password,user.getPassword());
			if (isPassTrue){
				LambdaQueryWrapper<BloodSugarUserRole> lambdaQueryWrapper = Wrappers.lambdaQuery();
				lambdaQueryWrapper.eq(BloodSugarUserRole::getUserId,user.getId());
				BloodSugarUserRole one = bloodSugarUserRoleService.getOne(lambdaQueryWrapper);

				LambdaQueryWrapper<BloodSugarRole> lambdaQueryWrapper1 = Wrappers.lambdaQuery();
				lambdaQueryWrapper1.eq(BloodSugarRole::getId,one.getRoleId());
				BloodSugarRole one1 = bloodSugarRoleService.getOne(lambdaQueryWrapper1);

				authenticate(username, password);
				UserDetails userDetails = jwtUserDetailsServiceImpl
						.loadUserByUsername(username);
				String newToken = jwtTokenUtil.generateToken(userDetails);
				JwtUser jwtUser = null;
				if(userDetails instanceof JwtUser){
					jwtUser = (JwtUser) userDetails;
				}
				Map<String,Object> map = new HashMap<>();
				user.setPassword(null);
				user.setToken("Bearer "+newToken);
				user.setRoleType(one1.getRoleName());
				map.put("user",user);
				assert jwtUser != null;
				map.put("appRole",jwtUser.getAppCustomInfo());
				map.put("pcRole",jwtUser.getPcCustomInfo());
				map.put("pcMenuDepartmentId",jwtUser.getPcMenuDepartmentId());

				String oldToken = String.valueOf(redisTemplate.opsForValue().get(String.valueOf(user.getId())));

				//删除旧的token
				redisTemplate.delete(String.valueOf(user.getId()));
				redisTemplate.delete(oldToken);
				//设置新的token
				redisTemplate.opsForValue().set(String.valueOf(user.getId()),newToken);
				redisTemplate.opsForValue().set(newToken,user);
				log.info("oldToken+++"+redisTemplate.opsForValue().get(String.valueOf(user.getId())));
				return Result.ok().message("登录成功").data(map);
			}else{
				return Result.error().message("账号或密码错误");
			}
		}else{
			return Result.error().message("用户名不存在");
		}
	}

	/**
	 * 认证用户名密码
	 * @title
	 * @author kukaha
	 * @updateTime  16:17
	 */
	private void authenticate(String username, String password) throws Exception {
		try {
			authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
		} catch (DisabledException e) {
			throw new Exception("USER_DISABLED", e);
		} catch (BadCredentialsException e) {
			throw new Exception("INVALID_CREDENTIALS", e);
		}
	}

	/**
	 * 获取用户权限信息
	 * @title
	 * @author kukaha
	 * @updateTime  16:18
	 */
	@PreAuthorize("isAuthenticated()")
	@ApiOperation(value = "根据jwt token 查看用户权限信息")
	@GetMapping("/token")
	public JwtUser getAuthenticatedUser(Authentication authentication) {
		JwtUser userInfo = (JwtUser) authentication.getPrincipal();
		System.out.println(userInfo);
		return userInfo;
	}

	/**
	 * 获取用户权限信息
	 * @title
	 * @author kukaha
	 * @updateTime  16:18
	 */
	@PreAuthorize("isAuthenticated()")
	@ApiOperation(value = "根据jwt token 查看用户权限信息")
	@GetMapping("/tokenTwo")
	public JwtUser getAuthenticatedUser(HttpServletRequest request) {
		String token = request.getHeader(tokenHeader).substring(7);
		String username = jwtTokenUtil.getUsernameFromToken(token);
		JwtUser user = (JwtUser) jwtUserDetailsServiceImpl.loadUserByUsername(username);
		return user;
	}


	/**
	 * 获取用户权限信息
	 * @title
	 * @author kukaha
	 * @updateTime  16:18
	 */
	@PreAuthorize("isAuthenticated()")
	@ApiOperation(value = "根据jwt token 查看用户权限信息")
	@GetMapping("/tokenThree")
	public JwtUser getAuthenticatedUser() {
		JwtUser userInfo = (JwtUser)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		System.out.println(userInfo);
		return userInfo;
	}
}

